/*
 * This code is property of CoreObjects. Use, duplication and disclosure
 * in any form without permission of copyright holder is prohibited.
 *
 */
package com.nen.session;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
 * Checks for valid login. Extracts session and user information.
 * Adds new cookies to response - jsessionid cookie and useremail cookie
 * 
 * @author amitm
 */
public class CookieFilter implements Filter {

    private static String JSESSIONID_COOKIE_NAME = "_nenjsid";
    private static String USEREMAIL_COOKIE_NAME = "_nenue";
    private static String COOKIE_DOMAIN_NAME = ".nenonline.org";
    private static String ONCE_PER_REQUEST_ATTR_NAME = "_cookie_filter_applied_";
    private static String COOKIE_ADDED_ATTR_NAME = "_cookie_added_";

    private static boolean isUserLoggedIn(HttpSession javaSession) {
        return javaSession != null && javaSession.getAttribute("loginUserDetails") != null;
    }

    public void init(FilterConfig fc) throws ServletException {
        System.out.println("Inside CookieFilter.init");
        JSESSIONID_COOKIE_NAME = NenUtils.getParamValue(fc.getInitParameter("JSESSIONID_COOKIE_NAME"), JSESSIONID_COOKIE_NAME);
        USEREMAIL_COOKIE_NAME = NenUtils.getParamValue(fc.getInitParameter("USEREMAIL_COOKIE_NAME"), USEREMAIL_COOKIE_NAME);
        COOKIE_DOMAIN_NAME = NenUtils.getParamValue(fc.getInitParameter("COOKIE_DOMAIN_NAME"), COOKIE_DOMAIN_NAME);
    }

    public void doFilter(ServletRequest request,
            ServletResponse response,
            FilterChain chain)
            throws IOException, ServletException {
        
        if (request.getAttribute(ONCE_PER_REQUEST_ATTR_NAME) == null) {
            
            HttpSession javaSession = ((HttpServletRequest) request).getSession(false);

            if (cookieAdditionCheck(javaSession)) {
                System.out.println("Login has happened. Setting additional cookies");

                String javaSessionId = javaSession.getId();
                System.out.println("Java session id = " + javaSessionId);
                Cookie[] cookies = ((HttpServletRequest) request).getCookies();

                Cookie jsidCookie = new Cookie(JSESSIONID_COOKIE_NAME, javaSessionId);
                jsidCookie.setDomain(COOKIE_DOMAIN_NAME);
                jsidCookie.setPath("/");
                Cookie useremailCookie = new Cookie(USEREMAIL_COOKIE_NAME, getUserEmail(javaSession));
                useremailCookie.setDomain(COOKIE_DOMAIN_NAME);
                useremailCookie.setPath("/");

                setCookie(cookies, (HttpServletResponse) response, jsidCookie, false);
                setCookie(cookies, (HttpServletResponse) response, useremailCookie, false);
                javaSession.setAttribute(COOKIE_ADDED_ATTR_NAME, Boolean.TRUE);
                System.out.println("Cookies set");
                request.setAttribute(ONCE_PER_REQUEST_ATTR_NAME, Boolean.TRUE);
                System.out.println("Attribute added to allow filter only once per request");
            }

            System.out.println("Pre chain.doFilter");
            chain.doFilter(request, response);
            System.out.println("Post chain.doFilter");
        } else {
            System.out.println("Skipping cookie filter as it is already applied on this request");
        }

        System.out.println("Exiting CookieFilter.doFilter");
    }

    private static boolean cookieAdditionCheck(HttpSession javaSession) {
        return isUserLoggedIn(javaSession)
                && javaSession.getAttribute(COOKIE_ADDED_ATTR_NAME) == null;
    }

    private static boolean setCookie(Cookie[] cookies, HttpServletResponse response, Cookie newCookie, boolean checkExisting) {
        Cookie existingCookie = null;
        boolean newCookieAdded = false;
        if(checkExisting) {
            existingCookie = getCookieWithName(cookies, newCookie.getName());
        }
        if (existingCookie!=null) {
            System.out.println("Cookie already exists! => " + getStringValue(existingCookie));
        } else {
            response.addCookie(newCookie);
            newCookieAdded = true;
            System.out.println("New cookie added => " + getStringValue(newCookie));
        }

        return newCookieAdded;
    }

    private static String getUserEmail(HttpSession session) {
        String userEmail = "";
        if (isUserLoggedIn(session)) {
            Object loginUserDetails = session.getAttribute("loginUserDetails");

            userEmail = NenUtils.getProperty(loginUserDetails, "userEmail", "");
        }

        return userEmail;
    }

    private static String getStringValue(Cookie cookie) {
        return "Name=" + cookie.getName() + ",value=" + cookie.getValue() + ",domain=" + cookie.getDomain() + ",path=" + cookie.getPath() + ",maxAge=" + cookie.getMaxAge();
    }

    private static Cookie getCookieWithName(Cookie[] cookies, String name) {
        Cookie returnCookie = null;
        if (cookies != null) {
            for (int i = 0; i < cookies.length; i++) {
                Cookie cookie = cookies[i];
                if (name.equals(cookie.getName())) {
                    returnCookie = cookie;
                }
            }
        }
        return returnCookie;
    }

    public void destroy() {
        System.out.println("Inside destroy");
    }

}
